Skip to content

Conversation

@yinanazhou
Copy link
Member

  • init create/delete instrument feature
  • refactor add name frontend to name row manager

ref: #406

preview:
image

- Add CreateInstrument Django view with form handling and validation
- Implement frontend UI with CreateInstrument TypeScript module
- Add CreateInstrumentValidator for frontend form validation
- Add CreateInstrumentManager for API interactions and DatabaseService
- Create error_codes and exceptions modules for structured error handling
- Add migration 0012 for instrument creation feature
- Update InstrumentName and AVResource models to support creation workflow
- Update management commands (import, download, index) for creation compatibility
- Update instrument views and templates with creation UI
- Update Docker Compose and nginx configurations
- Add comprehensive test suite for creation workflows

ref: #406
- Add Django DELETE endpoint with permission checks for user-created instruments
- Add confirmation modal template and delete button on detail page
- Add TypeScript DeleteInstrumentManager for modal interaction and API call
- Add Solr cleanup on successful deletion via transaction.on_commit
- Restrict delete access to instrument creator and superusers
- Create NameRowManager class to extract duplicated name row management logic
  (row creation, RTL support, add/remove rows, form data collection)
- Refactor AddNameManager to use NameRowManager via composition
- Refactor CreateInstrumentManager to use NameRowManager via composition
- Move AddName publish logic from entry point into AddNameManager for consistency
- Fix DeleteNameManager to use shared getCsrfToken utility instead of private method
- Update entry points (AddName.ts, CreateInstrument.ts) to follow consistent initialization pattern
Copy link
Contributor

@PouyaMohseni PouyaMohseni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from that, I also cannot access the instrument list endpoint. I have dropped all public schemas in Django and flushed the database, yet I still receive the following error when accessing the /instrument endpoint:

NoReverseMatch
django.urls.exceptions.NoReverseMatch: Reverse for 'instrument-detail' with arguments '('',)' not found. 1 pattern(s) tried: ['instrument/(?P<umil_id>[-a-zA-Z0-9_]+)/\\Z']

Do you have any suggestions for reindexing?

related_name="created_instruments",
help_text="User who created this instrument (null for Wikidata imports)",
)
source = models.CharField(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we decide to require sources for newly added entries? I believe Ich mentioned that an instrument's source should be defined by the sources of its names.

I'm not sure which approach is the best, but at the moment we don't seem to have a clear editorial workflow for instrument names. For example, what should happen if a verified instrument ends up with no verified names (e.g., all names are removed)? Should the instrument entry itself be deleted, or should it remain as an instrument without any names?

If we decide not to require sources for instruments, the solution is straightforward delete. However, if instruments do have sources, the action becomes less clear.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if not hbs_class:
return False
# Pattern: one digit (1-5), followed by another digit, optionally followed by more .digits
pattern = r"^[1-5][0-9](\.[0-9]+)*$"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is a correct validator for HBS numbers. HBS values can include plus and dash in addition to a dot. Also, the second number, like the first, should be between 1 and 5. More, 0 is not a valid value in HBS numbers. I verified this by checking the entries we pulled from Wikidata. You can also see the same function referenced in #511 NameValidator.ts.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is why I suggested you to put #511 on hold. Again, this is the MVP for the instrument creation feature. The main idea is to make it work. All the addition touchup should be addressed in separate PRs.

<a class="view-field notranslate"
href="https://www.wikidata.org/wiki/{{ instrument.wikidata_id }}"
target="_blank">{{ instrument.wikidata_id }}</a>
{% if instrument.is_user_created %}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the assumption that a user created instrument does not have a Wikidata ID is wrong. When pushed to Wikidata, they are indexed. So maybe change it to whether wikidata_id exists, as what you did with mimo_class.

<span>Add New Name: <span id="instrumentNameInModal" class="notranslate m-1"></span></span>
<br />
<small>Wikidata ID: <span id="instrumentWikidataIdInModal" class="notranslate m-1"></span></small>
<small>UMIL ID: <span id="instrumentUmilIdInModal" class="notranslate m-1"></span></small>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need UMIL ID here as it is something internal? Also, we don't show that in instrument detail. Mybe showing that only when Wikidata ID is null?

class="rounded mw-50"
onerror="this.onerror=null;this.src='{% static "assets/images/instruments/no-image.svg" %}';" />
<div class="ms-2 align-self-start">
{% if instrument.is_user_created and instrument.default_image.source_name %}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think showing any uploaded image without approval to logged-out users would be a good idea, as we are not sure about the license for use and the content.

Copy link
Member Author

@yinanazhou yinanazhou Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a separate issue/PR

class="rounded mw-50"
onerror="this.onerror=null;this.src='{% static "assets/images/instruments/no-image.svg" %}';" />
<div class="ms-2 align-self-start">
{% if instrument.is_user_created and instrument.default_image.source_name %}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe showing all image sources?

slug_field = "umil_id"
slug_url_kwarg = "umil_id"

def get_object(self, queryset=None):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am curious whether there is a good approach to have UMIL- before the instrument ID in every request.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wikidata_id is no longer required with the changes, using UMIL- is a better approach than exposing pk in the database

instrument.avresource_set.all().delete()

# Delete the instrument (InstrumentNames cascade automatically)
instrument.delete()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering whether it is better to perform soft delete or to retire the current UMIL id.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, but it should be handled in a separate issue/PR

)

# Only the creator or a superuser can delete
if not (request.user.is_superuser or instrument.created_by == request.user):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the original contributor of an instrument always have the ability to delete the instrument? There might be many other name contributions to that entry by other users, or we might have already pushed the instrument entry to Wikidata. If a user decides to delete their contribution, it could undermine the other contributions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this should be handled in a followup issue/PR

Copy link
Contributor

@PouyaMohseni PouyaMohseni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from that, I also cannot access the instrument list endpoint. I have dropped all public schemas in Django and flushed the database, yet I still receive the following error when accessing the /instrument endpoint:

NoReverseMatch
django.urls.exceptions.NoReverseMatch: Reverse for 'instrument-detail' with arguments '('',)' not found. 1 pattern(s) tried: ['instrument/(?P<umil_id>[-a-zA-Z0-9_]+)/\\Z']

Do you have any suggestions for reindexing?

@yinanazhou
Copy link
Member Author

Do you have any suggestions for reindexing?

Have you migrated yet?

@yinanazhou yinanazhou merged commit b6815a2 into develop Feb 10, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants